﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.Xml.Serialization;

namespace zEngine.Cameras
{
    public class FPSCamera : Camera
    {
        MouseState originalMouseState;
        float leftRightRotation = 0.0f;
        float upDownRotation = 0.0f;
        Matrix cameraRotation;

        /// <summary>
        /// Initializes a new instance of the FFSCamera class.
        /// </summary>
        public FPSCamera(Game game, Vector3 cameraPosition, Vector3 cameraTarget)
            : base(game, cameraPosition, cameraTarget)
        {
            Mouse.SetPosition(game.Window.ClientBounds.Width / 2, game.Window.ClientBounds.Height / 2);
            originalMouseState = Mouse.GetState();
        }

        public override void Update(GameTime gameTime)
        {
            MouseState currentState = Mouse.GetState();
            if (currentState != originalMouseState)
            {
                float xDifferent = currentState.X - originalMouseState.X;
                float yDifferent = currentState.Y - originalMouseState.Y;
                leftRightRotation -= Settings.FPSCamera_RotationSpeed * xDifferent;
                upDownRotation -= Settings.FPSCamera_RotationSpeed * yDifferent;

                cameraRotation = Matrix.CreateRotationX(upDownRotation)
                    * Matrix.CreateRotationY(leftRightRotation);

                UpdateViewMatrix();
                Mouse.SetPosition(Game.Window.ClientBounds.Width / 2, Game.Window.ClientBounds.Height / 2);
            }

            KeyboardState keysState = Keyboard.GetState();
            if (keysState.IsKeyDown(Keys.Up))
                AddToCameraPosition(new Vector3(0, 0, -1));
            if (keysState.IsKeyDown(Keys.Down))
                AddToCameraPosition(new Vector3(0, 0, 1));
            if (keysState.IsKeyDown(Keys.Right))
                AddToCameraPosition(new Vector3(1, 0, 0));
            if (keysState.IsKeyDown(Keys.Left))
                AddToCameraPosition(new Vector3(-1, 0, 0));
            if (keysState.IsKeyDown(Keys.PageUp))
                AddToCameraPosition(new Vector3(0, 1, 0));
            if (keysState.IsKeyDown(Keys.PageDown))
                AddToCameraPosition(new Vector3(0, -1, 0));
            if (keysState.IsKeyDown(Keys.Z))
                CameraTarget = new Vector3(0, 0, 0);

            base.Update(gameTime);
        }

        void AddToCameraPosition(Vector3 addVector)
        {
            Vector3 tranformedVector = Vector3.Transform(addVector, cameraRotation);
            CameraPosition += Settings.FPSCamera_MoveSpeed * tranformedVector;
            UpdateViewMatrix();
        }

        void UpdateViewMatrix()
        {
            CameraTarget = Vector3.Transform(new Vector3(0, 0, -1), cameraRotation);
            CameraTarget = CameraPosition + CameraTarget;

            CameraUp = Vector3.Transform(new Vector3(0, 1, 0), cameraRotation);
        }
    }
}
